#ifndef _HTTP_H_
#define _HTTP_H_
#include "oal.h"
enum HTTP_CODE
{
	REQUEST_MORE = 0,
	REQUEST_OK,
	REQUEST_ERROR
};
enum HTTP_CHECK
{
	CHECK_REQUEST_LINE = 0,//处理请求行
	CHECK_HEAD_LINE,//处理消息头
	CHECK_OK
};
enum LINE_STATE
{
	LINE_OK = 0,
	LINE_BAD,
	LINE_OPEN
};
typedef enum http_method
{
    GET,
    POST,
    BUTT
}HTTP_METHOD;
typedef struct chunk_info
{
    oal_int32   chunk_data_index;//chunk数据首地址
    oal_int32   chunk_size;//整个chunk的长度
    oal_bool    need_more;//此chunk是否完整
    oal_bool    is_new;//是否是新的chunk
    oal_int32   proced_size;//已读的长度
	oal_int8    chunk_ascii[12];
	oal_uint8   now_asii;
}Chunk_info;

/*如果需要处理消息体，需要子类自己实现*/
class http
{
public:
    oal_uint8      *data_addr;//接收buff的首地址，挂接到子类
    oal_int32       last_check_index;//上一次完整检查的位置
    oal_int32       read_limit_index;//数据的末尾位置
    oal_int32       check_index;//读取到的位置
    oal_bool        has_data_enrty;//是否有消息实体
    oal_bool        chunked;//是否chunk
    Chunk_info      chunk_data;
    oal_int32       content_length;//消息总长度
    oal_int32       proced_length;//已收到的长度
    string          URL;
    unordered_map<string,string>  request_header;
    HTTP_METHOD     method;
    HTTP_CHECK      http_state;//目前所处的状态，如果不是CHECK_OK表示目前正在解析头
	http()
	{

	}
    oal_void http_clear()
    {
        has_data_enrty = false;
        last_check_index = 0;
        read_limit_index = 0;
        check_index = 0;
        chunked = false;
        http_state = CHECK_REQUEST_LINE;
        memset(&chunk_data,0,sizeof(Chunk_info));
        request_header.clear();
        URL.clear();
        method = BUTT;
    }
    
    oal_int8 parse_endline()
    {
        last_check_index = check_index;
	    while (check_index < read_limit_index)
	    {
		    if (data_addr[check_index] == '\n' )
		    {
			    chunk_data.chunk_ascii[chunk_data.now_asii++] = data_addr[check_index];
				check_index++;
				return 0;
		    }
		    else
		    {
				chunk_data.chunk_ascii[chunk_data.now_asii++] = data_addr[check_index];
			    check_index++;
		    }
		}
	    return -1;
    }
    LINE_STATE parse_line()
    {
        last_check_index = check_index;
	    while (check_index < read_limit_index)
	    {
		    if (data_addr[check_index] == '\n' )
		    {
			    if (data_addr[check_index-1] == '\r')//有必要做这个检查吗？
			    {
					#ifdef _HAI_TEST_
					int  chunk_len ;
					data_addr[check_index-1] = 0;
                    chunk_len = atoi((char *)data_addr+last_check_index);
					printf("the chunk len [%d]\n",chunk_len);
					#endif
					check_index++;
				    return LINE_OK;
			    }
			    else
			    {
				    printf("LINE_BAD\n");
				    check_index++;
				    return LINE_BAD;
			    }
		    }
		    else
		    {
			    check_index++;
		    }
	    }
		check_index = last_check_index;
	    return LINE_OPEN;
    }
    HTTP_CODE parse_request_header()
    {
        oal_int8* temp = (oal_int8 *)(data_addr + last_check_index);
	    if (*temp == '\r' && *(temp + 1) == '\n' || *temp == '\n')
	    {
		    if(request_header.find("Encoding") != request_header.end() && request_header["Encoding"] == "chunked")
            {
                chunked = true;
                has_data_enrty = true;
            }
            else if(request_header.find("Content-Length") != request_header.end() )
            {
                string length = request_header["Content-Length"];
                content_length = atoi(length.c_str());
                proced_length = 0;
                chunked = false;
                has_data_enrty = true;
            }
            else
            {
                has_data_enrty = false;
            }
            http_state = CHECK_OK;
		    return REQUEST_OK;
	    }
	    oal_int8* str = strpbrk(temp,":");
	    if (str == oal_ptr_null)
	    {
		    return REQUEST_ERROR;
	    }
	    oal_uint16 len = str - temp;
	    string name(temp,len);
	    printf("head [%s]\n",name.c_str());
	    temp = str + 1;
	    str = strpbrk(temp, "\r\n");
	    len = str - temp;
	    //oal_print("len:  [%d]  str [%s]\n",len,temp);

	    string value(temp,len);
	    printf("value [%s]\n",value.c_str());
	    request_header.insert(pair<string,string>(name, value));
	    //oal_print("header size is  [%d]\n",request_header.size());
	    return REQUEST_OK;
    }

    HTTP_CODE parse_request_line()
    {
        string version_of_request;
        string method_s;
        oal_int8* head = (oal_int8 *)(data_addr + last_check_index);
	    oal_int8* temp = head;
	    oal_int8* str = strpbrk(temp," \t");//返回空格或者'\t'所在位置
	    if (str == oal_ptr_null)
	    {
		    return REQUEST_ERROR;
	    }
	    oal_uint8  len = str - temp;
	    method_s.append(temp, len);
	    temp = str + 1;
	    str  = strpbrk(temp, " \t");
	    *str = '\0';
	    printf("method : [%s]\n", method_s.c_str());
        if(method_s == "POST")
        {
            method = POST;
        }
        else if(method_s == "GET")
        {
            method = GET;
        }
        else
        {
            method = BUTT;
        }
	    oal_int8* str1 = str;
	    if (str == oal_ptr_null)
	    {
		    return REQUEST_ERROR;
	    }
	    len = str - temp;
	    URL.append(temp + 1, len - 1);
	    printf("url : [%s]\n", URL.c_str());
	    temp = str1 + 1;
	    str = strpbrk(temp, "\r\n");
	    if (str == oal_ptr_null)
	    {
		    return REQUEST_ERROR;
	    }
	    len = str - temp;
	    version_of_request.append(temp, len);
	    printf("version : [%s]\n", version_of_request.c_str());
	    http_state = CHECK_HEAD_LINE;
	    return REQUEST_OK;
    }
    HTTP_CODE  parse_content()
    {
        if(http_state == CHECK_OK)
        {
			//printf("ddddd");
            return REQUEST_OK;
        }
	    //oal_print("parsecontent 1111111\n");
	    while(parse_line() == LINE_OK)
	    {
		    //oal_print("parsecontent 222222\n");
		    if (http_state == CHECK_REQUEST_LINE)
		    {
		    	//oal_print("parsecontent 333333\n");
			    parse_request_line();
		    }
		    else if (http_state == CHECK_HEAD_LINE)
		    {
			    //oal_print("parsecontent 4444444\n");
                //
			    parse_request_header();
            }
            if (http_state == CHECK_OK)
		    {
                return REQUEST_OK;
	        }
        }
        return REQUEST_MORE;
	}
};
#endif